home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / mcr3.c < prev    next >
C/C++ Source or Header  |  2000-05-13  |  14KB  |  561 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw/mcr3.c
  4.  
  5.     Functions to emulate the video hardware of an mcr3-style machine.
  6.  
  7. ***************************************************************************/
  8.  
  9. #include "driver.h"
  10. #include "artwork.h"
  11. #include "machine/mcr.h"
  12. #include "vidhrdw/generic.h"
  13.  
  14.  
  15. #ifndef MIN
  16. #define MIN(x,y) (x)<(y)?(x):(y)
  17. #endif
  18.  
  19. /* These are used to align Discs of Tron with the backdrop */
  20. #define DOTRON_X_START 144
  21. #define DOTRON_Y_START 40
  22. #define DOTRON_HORIZON 138
  23.  
  24.  
  25.  
  26. /*************************************
  27.  *
  28.  *    Global variables
  29.  *
  30.  *************************************/
  31.  
  32. /* Spy Hunter hardware extras */
  33. UINT8 spyhunt_sprite_color_mask;
  34. INT16 spyhunt_scrollx, spyhunt_scrolly;
  35. INT16 spyhunt_scroll_offset;
  36. UINT8 spyhunt_draw_lamps;
  37. UINT8 spyhunt_lamp[8];
  38.  
  39. UINT8 *spyhunt_alpharam;
  40. size_t spyhunt_alpharam_size;
  41.  
  42.  
  43.  
  44. /*************************************
  45.  *
  46.  *    Local variables
  47.  *
  48.  *************************************/
  49.  
  50. /* Spy Hunter-specific scrolling background */
  51. static struct osd_bitmap *spyhunt_backbitmap;
  52.  
  53. /* Discs of Tron artwork globals */
  54. static UINT8 dotron_palettes[3][3*256];
  55. static UINT8 light_status;
  56.  
  57. static UINT8 last_cocktail_flip;
  58.  
  59.  
  60.  
  61. /*************************************
  62.  *
  63.  *    Palette RAM writes
  64.  *
  65.  *************************************/
  66.  
  67. WRITE_HANDLER( mcr3_paletteram_w )
  68. {
  69.     int r, g, b;
  70.  
  71.     paletteram[offset] = data;
  72.     offset &= 0x7f;
  73.  
  74.     /* high bit of red comes from low bit of address */
  75.     r = ((offset & 1) << 2) + (data >> 6);
  76.     g = (data >> 0) & 7;
  77.     b = (data >> 3) & 7;
  78.  
  79.     /* up to 8 bits */
  80.     r = (r << 5) | (r << 2) | (r >> 1);
  81.     g = (g << 5) | (g << 2) | (g >> 1);
  82.     b = (b << 5) | (b << 2) | (b >> 1);
  83.  
  84.     palette_change_color(offset / 2, r, g, b);
  85. }
  86.  
  87.  
  88.  
  89. /*************************************
  90.  *
  91.  *    Video RAM writes
  92.  *
  93.  *************************************/
  94.  
  95. WRITE_HANDLER( mcr3_videoram_w )
  96. {
  97.     if (videoram[offset] != data)
  98.     {
  99.         dirtybuffer[offset & ~1] = 1;
  100.         videoram[offset] = data;
  101.     }
  102. }
  103.  
  104.  
  105.  
  106. /*************************************
  107.  *
  108.  *    Background update
  109.  *
  110.  *************************************/
  111.  
  112. static void mcr3_update_background(struct osd_bitmap *bitmap, UINT8 color_xor)
  113. {
  114.     int offs;
  115.  
  116.     /* for every character in the Video RAM, check if it has been modified */
  117.     /* since last time and update it accordingly. */
  118.     for (offs = videoram_size - 2; offs >= 0; offs -= 2)
  119.     {
  120.         if (dirtybuffer[offs])
  121.         {
  122.             int mx = (offs / 2) % 32;
  123.             int my = (offs / 2) / 32;
  124.             int attr = videoram[offs + 1];
  125.             int color = ((attr & 0x30) >> 4) ^ color_xor;
  126.             int code = videoram[offs] + 256 * (attr & 0x03);
  127.  
  128.             if (!mcr_cocktail_flip)
  129.                 drawgfx(bitmap, Machine->gfx[0], code, color, attr & 0x04, attr & 0x08,
  130.                         16 * mx, 16 * my, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  131.             else
  132.                 drawgfx(bitmap, Machine->gfx[0], code, color, !(attr & 0x04), !(attr & 0x08),
  133.                         16 * (31 - mx), 16 * (29 - my), &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  134.  
  135.             dirtybuffer[offs] = 0;
  136.         }
  137.     }
  138. }
  139.  
  140.  
  141.  
  142. /*************************************
  143.  *
  144.  *    Sprite update
  145.  *
  146.  *************************************/
  147.  
  148. void mcr3_update_sprites(struct osd_bitmap *bitmap, int color_mask, int code_xor, int dx, int dy)
  149. {
  150.     int offs;
  151.  
  152.     /* loop over sprite RAM */
  153.     for (offs = 0; offs < spriteram_size; offs += 4)
  154.     {
  155.         int code, color, flipx, flipy, sx, sy, flags;
  156.  
  157.         /* skip if zero */
  158.         if (spriteram[offs] == 0)
  159.             continue;
  160.  
  161.         /* extract the bits of information */
  162.         flags = spriteram[offs + 1];
  163.         code = spriteram[offs + 2] + 256 * ((flags >> 3) & 0x01);
  164.         color = ~flags & color_mask;
  165.         flipx = flags & 0x10;
  166.         flipy = flags & 0x20;
  167.         sx = (spriteram[offs + 3] - 3) * 2;
  168.         sy = (241 - spriteram[offs]) * 2;
  169.  
  170.         code ^= code_xor;
  171.  
  172.         sx += dx;
  173.         sy += dy;
  174.  
  175.         /* draw the sprite */
  176.         if (!mcr_cocktail_flip)
  177.             drawgfx(bitmap, Machine->gfx[1], code, color, flipx, flipy, sx, sy,
  178.                     &Machine->drv->visible_area, TRANSPARENCY_PEN, 0);
  179.         else
  180.             drawgfx(bitmap, Machine->gfx[1], code, color, !flipx, !flipy, 480 - sx, 452 - sy,
  181.                     &Machine->drv->visible_area, TRANSPARENCY_PEN, 0);
  182.  
  183.         /* sprites use color 0 for background pen and 8 for the 'under tile' pen.
  184.             The color 8 is used to cover over other sprites. */
  185.         if (Machine->gfx[1]->pen_usage[code] & 0x0100)
  186.         {
  187.             struct rectangle clip;
  188.  
  189.             clip.min_x = sx;
  190.             clip.max_x = sx + 31;
  191.             clip.min_y = sy;
  192.             clip.max_y = sy + 31;
  193.  
  194.             copybitmap(bitmap, tmpbitmap, 0, 0, 0, 0, &clip, TRANSPARENCY_THROUGH, Machine->pens[8 + color * 16]);
  195.         }
  196.     }
  197. }
  198.  
  199.  
  200.  
  201. /*************************************
  202.  *
  203.  *    Generic MCR3 redraw
  204.  *
  205.  *************************************/
  206.  
  207. void mcr3_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  208. {
  209.     /* mark everything dirty on a cocktail flip change */
  210.     if (palette_recalc() || last_cocktail_flip != mcr_cocktail_flip)
  211.         memset(dirtybuffer, 1, videoram_size);
  212.     last_cocktail_flip = mcr_cocktail_flip;
  213.  
  214.     /* redraw the background */
  215.     mcr3_update_background(tmpbitmap, 0);
  216.  
  217.     /* copy it to the destination */
  218.     copybitmap(bitmap, tmpbitmap, 0, 0, 0, 0, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  219.  
  220.     /* draw the sprites */
  221.     mcr3_update_sprites(bitmap, 0x03, 0, 0, 0);
  222. }
  223.  
  224.  
  225.  
  226. /*************************************
  227.  *
  228.  *    MCR monoboard-specific redraw
  229.  *
  230.  *************************************/
  231.  
  232. void mcrmono_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  233. {
  234.     if (palette_recalc())
  235.         memset(dirtybuffer, 1, videoram_size);
  236.  
  237.     /* redraw the background */
  238.     mcr3_update_background(tmpbitmap, 3);
  239.  
  240.     /* copy it to the destination */
  241.     copybitmap(bitmap, tmpbitmap, 0, 0, 0, 0, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  242.  
  243.     /* draw the sprites */
  244.     mcr3_update_sprites(bitmap, 0x03, 0, 0, 0);
  245. }
  246.  
  247.  
  248.  
  249. /*************************************
  250.  *
  251.  *    Spy Hunter-specific color PROM decoder
  252.  *
  253.  *************************************/
  254.  
  255. void spyhunt_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable, const unsigned char *color_prom)
  256. {
  257.     /* add some colors for the alpha RAM */
  258.     palette[(8*16)*3+0] = 0;
  259.     palette[(8*16)*3+1] = 0;
  260.     palette[(8*16)*3+2] = 0;
  261.     palette[(8*16+1)*3+0] = 0;
  262.     palette[(8*16+1)*3+1] = 255;
  263.     palette[(8*16+1)*3+2] = 0;
  264.     palette[(8*16+2)*3+0] = 0;
  265.     palette[(8*16+2)*3+1] = 0;
  266.     palette[(8*16+2)*3+2] = 255;
  267.     palette[(8*16+3)*3+0] = 255;
  268.     palette[(8*16+3)*3+1] = 255;
  269.     palette[(8*16+3)*3+2] = 255;
  270.  
  271.     /* put them into the color table */
  272.     colortable[8*16+0] = 8*16;
  273.     colortable[8*16+1] = 8*16+1;
  274.     colortable[8*16+2] = 8*16+2;
  275.     colortable[8*16+3] = 8*16+3;
  276. }
  277.  
  278.  
  279.  
  280. /*************************************
  281.  *
  282.  *    Spy Hunter-specific video startup
  283.  *
  284.  *************************************/
  285.  
  286. int spyhunt_vh_start(void)
  287. {
  288.     /* allocate our own dirty buffer */
  289.     dirtybuffer = malloc(videoram_size);
  290.     if (!dirtybuffer)
  291.         return 1;
  292.     memset(dirtybuffer, 1, videoram_size);
  293.  
  294.     /* allocate a bitmap for the background */
  295.     spyhunt_backbitmap = osd_create_bitmap(64*64, 32*32);
  296.     if (!spyhunt_backbitmap)
  297.     {
  298.         free(dirtybuffer);
  299.         return 1;
  300.     }
  301.  
  302.     /* reset the scrolling */
  303.     spyhunt_scrollx = spyhunt_scrolly = 0;
  304.  
  305.     return 0;
  306. }
  307.  
  308.  
  309.  
  310. /*************************************
  311.  *
  312.  *    Spy Hunter-specific video shutdown
  313.  *
  314.  *************************************/
  315.  
  316. void spyhunt_vh_stop(void)
  317. {
  318.     /* free the buffers */
  319.     osd_free_bitmap(spyhunt_backbitmap);
  320.     free(dirtybuffer);
  321. }
  322.  
  323.  
  324.  
  325. /*************************************
  326.  *
  327.  *    Spy Hunter-specific redraw
  328.  *
  329.  *************************************/
  330.  
  331. void spyhunt_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  332. {
  333.     static const struct rectangle clip = { 0, 30*16-1, 0, 30*16-1 };
  334.     int offs, scrollx, scrolly;
  335.  
  336.     if (palette_recalc())
  337.         memset(dirtybuffer, 1, videoram_size);
  338.  
  339.     /* for every character in the Video RAM, check if it has been modified */
  340.     /* since last time and update it accordingly. */
  341.     for (offs = videoram_size - 1; offs >= 0; offs--)
  342.     {
  343.         if (dirtybuffer[offs])
  344.         {
  345.             int code = videoram[offs];
  346.             int vflip = code & 0x40;
  347.             int mx = (offs >> 4) & 0x3f;
  348.             int my = (offs & 0x0f) | ((offs >> 6) & 0x10);
  349.  
  350.             code = (code & 0x3f) | ((code & 0x80) >> 1);
  351.  
  352.             drawgfx(spyhunt_backbitmap, Machine->gfx[0], code, 0, 0, vflip,
  353.                     64 * mx, 32 * my, NULL, TRANSPARENCY_NONE, 0);
  354.  
  355.             dirtybuffer[offs] = 0;
  356.         }
  357.     }
  358.  
  359.     /* copy it to the destination */
  360.     scrollx = -spyhunt_scrollx * 2 + spyhunt_scroll_offset;
  361.     scrolly = -spyhunt_scrolly * 2;
  362.     copyscrollbitmap(bitmap, spyhunt_backbitmap, 1, &scrollx, 1, &scrolly, &clip, TRANSPARENCY_NONE, 0);
  363.  
  364.     /* draw the sprites */
  365.     mcr3_update_sprites(bitmap, spyhunt_sprite_color_mask, 0x80, -12, 0);
  366.  
  367.     /* render any characters on top */
  368.     for (offs = spyhunt_alpharam_size - 1; offs >= 0; offs--)
  369.     {
  370.         int ch = spyhunt_alpharam[offs];
  371.         if (ch)
  372.         {
  373.             int mx = offs / 32;
  374.             int my = offs % 32;
  375.  
  376.             drawgfx(bitmap, Machine->gfx[2], ch, 0, 0, 0,
  377.                     16 * mx - 16, 16 * my, &clip, TRANSPARENCY_PEN, 0);
  378.         }
  379.     }
  380.  
  381.     /* lamp indicators */
  382.     if (spyhunt_draw_lamps)
  383.     {
  384.         char buffer[32];
  385.  
  386.         sprintf(buffer, "%s  %s  %s  %s  %s",
  387.                 spyhunt_lamp[0] ? "OIL" : "   ",
  388.                 spyhunt_lamp[1] ? "MISSILE" : "       ",
  389.                 spyhunt_lamp[2] ? "VAN" : "   ",
  390.                 spyhunt_lamp[3] ? "SMOKE" : "     ",
  391.                 spyhunt_lamp[4] ? "GUNS" : "    ");
  392.         for (offs = 0; offs < 30; offs++)
  393.             drawgfx(bitmap, Machine->gfx[2], buffer[offs], 0, 0, 0,
  394.                     30 * 16, (29 - offs) * 16, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  395.     }
  396. }
  397.  
  398.  
  399.  
  400. /*************************************
  401.  *
  402.  *    Discs of Tron-specific video startup
  403.  *
  404.  *************************************/
  405.  
  406. int dotron_vh_start(void)
  407. {
  408.     int i, x, y;
  409.  
  410.     /* do generic initialization to start */
  411.     if (generic_vh_start())
  412.         return 1;
  413.  
  414.     backdrop_load("dotron.png", 64, Machine->drv->total_colors-64);
  415.  
  416.     /* if we got it, compute palettes */
  417.     if (artwork_backdrop)
  418.     {
  419.         /* from the horizon upwards, use the second palette */
  420.         for (y = 0; y < DOTRON_HORIZON; y++)
  421.             for (x = 0; x < artwork_backdrop->artwork->width; x++)
  422.             {
  423.                 int newpixel = read_pixel(artwork_backdrop->orig_artwork, x, y) + 95;
  424.                 plot_pixel(artwork_backdrop->orig_artwork, x, y, newpixel);
  425.             }
  426.  
  427.         backdrop_refresh(artwork_backdrop);
  428.  
  429.         /* create palettes with different levels of brightness */
  430.         memcpy(dotron_palettes[0], artwork_backdrop->orig_palette, 3 * artwork_backdrop->num_pens_used);
  431.         for (i = 0; i < artwork_backdrop->num_pens_used; i++)
  432.         {
  433.             /* only boost red and blue */
  434.             dotron_palettes[1][i * 3 + 0] = MIN(artwork_backdrop->orig_palette[i * 3] * 2, 255);
  435.             dotron_palettes[1][i * 3 + 1] = artwork_backdrop->orig_palette[i * 3 + 1];
  436.             dotron_palettes[1][i * 3 + 2] = MIN(artwork_backdrop->orig_palette[i * 3 + 2] * 2, 255);
  437.             dotron_palettes[2][i * 3 + 0] = MIN(artwork_backdrop->orig_palette[i * 3] * 3, 255);
  438.             dotron_palettes[2][i * 3 + 1] = artwork_backdrop->orig_palette[i * 3 + 1];
  439.             dotron_palettes[2][i * 3 + 2] = MIN(artwork_backdrop->orig_palette[i * 3 + 2] * 3, 255);
  440.         }
  441.  
  442.         logerror("Backdrop loaded.\n");
  443.     }
  444.  
  445.     return 0;
  446. }
  447.  
  448.  
  449.  
  450. /*************************************
  451.  *
  452.  *    Discs of Tron light management
  453.  *
  454.  *************************************/
  455.  
  456. void dotron_change_light(int light)
  457. {
  458.     light_status = light;
  459. }
  460.  
  461.  
  462. static void dotron_change_palette(int which)
  463. {
  464.     UINT8 *new_palette;
  465.     int i, offset;
  466.  
  467.     /* get the palette indices */
  468.     offset = artwork_backdrop->start_pen + 95;
  469.     new_palette = dotron_palettes[which];
  470.  
  471.     /* update the palette entries */
  472.     for (i = 0; i < artwork_backdrop->num_pens_used; i++)
  473.         palette_change_color(i + offset, new_palette[i * 3], new_palette[i * 3 + 1], new_palette[i * 3 + 2]);
  474. }
  475.  
  476.  
  477.  
  478. /*************************************
  479.  *
  480.  *    Discs of Tron-specific redraw
  481.  *
  482.  *************************************/
  483.  
  484. void dotron_vh_screenrefresh(struct osd_bitmap *bitmap, int full_refresh)
  485. {
  486.     struct rectangle sclip;
  487.     int offs;
  488.  
  489.     /* handle background lights */
  490.     if (artwork_backdrop != NULL)
  491.     {
  492.         int light = light_status & 1;
  493.         if ((light_status & 2) && (cpu_getcurrentframe() & 1)) light++;    /* strobe */
  494.         dotron_change_palette(light);
  495.         /* This is necessary because Discs of Tron modifies the palette */
  496.         if (backdrop_black_recalc())
  497.             memset(dirtybuffer, 1, videoram_size);
  498.  
  499.     }
  500.  
  501.     if (full_refresh || palette_recalc())
  502.     {
  503.         if (artwork_backdrop)
  504.         {
  505.             backdrop_refresh(artwork_backdrop);
  506.             copybitmap(tmpbitmap, artwork_backdrop->artwork, 0, 0, 0, 0, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  507.             copybitmap(bitmap, artwork_backdrop->artwork, 0, 0, 0, 0, &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  508.             osd_mark_dirty(0,0,bitmap->width, bitmap->height, 0);
  509.         }
  510.         memset(dirtybuffer, 1 ,videoram_size);
  511.     }
  512.  
  513.     /* Screen clip, because our backdrop is a different resolution than the game */
  514.     sclip.min_x = DOTRON_X_START + 0;
  515.     sclip.max_x = DOTRON_X_START + 32*16 - 1;
  516.     sclip.min_y = DOTRON_Y_START + 0;
  517.     sclip.max_y = DOTRON_Y_START + 30*16 - 1;
  518.  
  519.     /* for every character in the Video RAM, check if it has been modified */
  520.     /* since last time and update it accordingly. */
  521.     for (offs = videoram_size - 2; offs >= 0; offs -= 2)
  522.     {
  523.         if (dirtybuffer[offs])
  524.         {
  525.             int attr = videoram[offs+1];
  526.             int code = videoram[offs] + 256 * (attr & 0x03);
  527.             int color = (attr & 0x30) >> 4;
  528.             int mx = ((offs / 2) % 32) * 16;
  529.             int my = ((offs / 2) / 32) * 16;
  530.  
  531.             /* center for the backdrop */
  532.             mx += DOTRON_X_START;
  533.             my += DOTRON_Y_START;
  534.  
  535.             drawgfx(tmpbitmap, Machine->gfx[0], code, color, attr & 0x04, attr & 0x08,
  536.                     mx, my, &sclip, TRANSPARENCY_NONE, 0);
  537.  
  538.             if (artwork_backdrop != NULL)
  539.             {
  540.                 struct rectangle bclip;
  541.  
  542.                 bclip.min_x = mx;
  543.                 bclip.max_x = mx + 16 - 1;
  544.                 bclip.min_y = my;
  545.                 bclip.max_y = my + 16 - 1;
  546.  
  547.                 draw_backdrop(tmpbitmap, artwork_backdrop->artwork, 0, 0, &bclip);
  548.             }
  549.  
  550.             dirtybuffer[offs] = 0;
  551.         }
  552.     }
  553.  
  554.     /* copy the resulting bitmap to the screen */
  555.     copybitmap(bitmap, tmpbitmap, 0, 0, 0, 0, 0, TRANSPARENCY_NONE, 0);
  556.  
  557.     /* draw the sprites */
  558.     mcr3_update_sprites(bitmap, 0x03, 0, DOTRON_X_START, DOTRON_Y_START);
  559. }
  560.  
  561.